using System;
using System.Diagnostics;
using System.Reflection;

namespace CommonTypes
{
    /// <summary>
    /// Attribute to tag the performance counters for a given class to a performance counter category.
    /// </summary>
    /// <remarks>
    /// Attribute to tag the performance counters for a given class to a performance counter category.
    /// </remarks>
    [AttributeUsage(AttributeTargets.Class)]
    public class PerformanceCounterCategoryAttribute : Attribute
    {
        private string name;
        private string help;
        private PerformanceCounterCategoryType categoryType;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <remarks>
        /// PerformanceCounterCategoryType defaults to Unknown
        /// </remarks>
        /// <param name="name">Performance counter category name.</param>
        public PerformanceCounterCategoryAttribute(string name)
            : this(name, null, PerformanceCounterCategoryType.Unknown)
        {
            // nothing to do
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <remarks>
        /// PerformanceCounterCategoryType defaults to Unknown
        /// </remarks>
        /// <param name="name">Performance counter category name.</param>
        /// <param name="help">Performance counter category help.</param>
        public PerformanceCounterCategoryAttribute(string name, string help)
            : this(name, help, PerformanceCounterCategoryType.Unknown)
        {
            // nothing to do
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <remarks>
        /// Constructor
        /// </remarks>
        /// <param name="name">Performance counter category name.</param>
        /// <param name="categoryType">Performance counter category type.</param>
        public PerformanceCounterCategoryAttribute(string name, PerformanceCounterCategoryType categoryType)
            : this(name, null, categoryType)
        {
            // nothing to do
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <remarks>
        /// Constructor
        /// </remarks>
        /// <param name="name">Performance counter category name.</param>
        /// <param name="help">Performance counter category help.</param>
        /// <param name="categoryType">Performance counter category type.</param>
        public PerformanceCounterCategoryAttribute(string name, string help, PerformanceCounterCategoryType categoryType)
        {
            this.name = name;
            this.help = help;
            this.categoryType = categoryType;
        }

        /// <summary>
        /// Gets the performance counter category.
        /// </summary>
        /// <remarks>
        /// Gets the performance counter category.
        /// </remarks>
        public string Name
        {
            get { return name; }
        }

        /// <summary>
        /// Gets the performance counter category help.
        /// </summary>
        /// <remarks>
        /// Gets the performance counter category help.
        /// </remarks>
        public string Help
        {
            get { return help; }
        }

        /// <summary>
        /// Gets the performance counter category type.
        /// </summary>
        /// <remarks>
        /// Default is Unknown.
        /// </remarks>
        public PerformanceCounterCategoryType CategoryType
        {
            get { return categoryType; }
        }
    }

    /// <summary>
    /// Defines a performance counter for the class that it is tagged with it.
    /// </summary>
    [AttributeUsage(AttributeTargets.Field)]
    public class PerformanceCounterAttribute : Attribute
    {
        #region Private Members

        string name;
        string help;
        string instance;
        PerformanceCounterType type;

        #endregion

        #region Constructor

        /// <summary>
        /// Creates a new performance counter attribute with the given counter name.
        /// </summary>
        /// <remarks>
        /// Creates a new performance counter attribute with the given counter name.
        /// </remarks>
        /// <param name="name">Counter name.</param>
        public PerformanceCounterAttribute(string name)
            : this(name, null, PerformanceCounterType.NumberOfItems64, null)
        {
            // nothing to do
        }

        /// <summary>
        /// Creates a new performance counter attribute with the given counter name and type.
        /// </summary>
        /// <remarks>
        /// Creates a new performance counter attribute with the given counter name and type.
        /// </remarks>
        /// <param name="name">Counter name.</param>
        /// <param name="type">Counter type.</param>
        public PerformanceCounterAttribute(string name, PerformanceCounterType type)
            : this(name, null, type, null)
        {
            // nothing to do
        }

        /// <summary>
        /// Creates a new performance counter attribute with the given counter name and type.
        /// </summary>
        /// <remarks>
        /// Creates a new performance counter attribute with the given counter name and type.
        /// </remarks>
        /// <param name="name">Counter name.</param>
        /// <param name="type">Counter type.</param>
        /// <param name="instance">Counter instance name.</param>
        public PerformanceCounterAttribute(string name, PerformanceCounterType type, string instance)
            : this(name, null, type, instance)
        {
            // nothing to do
        }

        /// <summary>
        /// Creates a new performance counter attribute with the given counter name and type.
        /// </summary>
        /// <remarks>
        /// Creates a new performance counter attribute with the given counter name and type.
        /// </remarks>
        /// <param name="name">Counter name.</param>
        /// <param name="help">Counter help.</param>
        /// <param name="type">Counter type.</param>
        public PerformanceCounterAttribute(string name, string help, PerformanceCounterType type)
            : this(name, help, type, null)
        {
            // nothing to do
        }

        /// <summary>
        /// Creates a new performance counter attribute with the given counter name, help, member name and type.
        /// </summary>
        /// <remarks>
        /// Creates a new performance counter attribute with the given counter name, help, member name and type.
        /// </remarks>
        /// <param name="name">Counter name.</param>
        /// <param name="type">Counter type.</param>
        /// <param name="help">Counter help.</param>
        /// <param name="instance">Counter instance name.</param>
        public PerformanceCounterAttribute(string name, string help, PerformanceCounterType type, string instance)
        {
            this.name = name;
            this.instance = (instance == null) ? string.Empty : instance;
            this.help = help;
            this.type = type;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets the performance counter name.
        /// </summary>
        /// <remarks>
        /// Gets the performance counter name.
        /// </remarks>
        public string Name { get { return name; } }

        /// <summary>
        /// Gets the performance counter instance name.
        /// </summary>
        /// <remarks>
        /// Gets the performance counter instance name.
        /// </remarks>
        public string Instance { get { return instance; } }

        /// <summary>
        /// Gets the performance counter help.
        /// </summary>
        /// <remarks>
        /// Gets the performance counter help.
        /// </remarks>
        public string Help { get { return help; } }

        /// <summary>
        /// Gets the type of the performance counter.
        /// </summary>
        /// <remarks>
        /// Gets the type of the performance counter.
        /// </remarks>
        public PerformanceCounterType Type { get { return type; } }

        #endregion
    }

    /// <summary>
    /// Wrapper and Helper class for a category of performance counters.
    /// </summary>
    /// <remarks>
    /// Wrapper and Helper class for a category of performance counters.
    /// </remarks>
    public class PerformanceCounterFactory
    {
        #region Private Members

        private string categoryName;
        private string categoryHelp;
        private PerformanceCounterCategoryType categoryType;
        private CounterCreationDataCollection counters;

        #endregion

        #region Constructor

        /// <summary>
        /// Creates a new performance counter category with the given name and help description.
        /// </summary>
        /// <remarks>
        /// Creates a new performance counter category with the given name and help description.
        /// </remarks>
        /// <param name="categoryName">Performance counter category name.</param>
        /// <param name="categoryHelp">Performance counter category help text.</param>
        public PerformanceCounterFactory(string categoryName, string categoryHelp)
        {
            this.categoryName = categoryName;
            this.categoryHelp = categoryHelp;
            this.categoryType = PerformanceCounterCategoryType.Unknown;
            counters = new CounterCreationDataCollection();
        }

        /// <summary>
        /// Creates a new performance counter category with the given name.
        /// </summary>
        /// <remarks>
        /// Creates a new performance counter category with the given name.
        /// </remarks>
        /// <param name="categoryName"></param>
        public PerformanceCounterFactory(string categoryName)
            : this(categoryName, null)
        {
            // nothing to do
        }

        /// <summary>
        /// Creates a new category for the specified type.
        /// </summary>
        /// <remarks>
        /// Type must have <c>PerformanceCounterCategoryAttribute</c> and <c>PerformanceCounterAttributes</c> set.
        /// </remarks>
        /// <exception cref="ArgumentException">
        /// Thrown if the specified type has no performance counter category attribute set.
        /// </exception>
        /// <param name="type">Type to create Performance counters for.</param>
        public PerformanceCounterFactory(Type type)
        {
            counters = new CounterCreationDataCollection();

            PerformanceCounterCategoryAttribute category = GetCategory(type);
            if (PerformanceCounterCategory.Exists(category.Name)) return;
            if (category == null) throw new ArgumentException(String.Format("Type {0} has no PerformanceCounterCategory attribute", type.Name), "type");

            this.categoryName = category.Name;
            this.categoryHelp = category.Help;
            this.categoryType = category.CategoryType;

            _AddCounters(type);
            PerformanceCounterCategory.Create(categoryName, categoryHelp, counters);
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets the performance counter category name.
        /// </summary>
        /// <value>
        /// Performance counter category name.
        /// </value>
        public string Name
        {
            get { return categoryName; }
        }

        /// <summary>
        /// Gets the performance counter category help.
        /// </summary>
        /// <value>
        /// Performance counter category help.
        /// </value>
        public string Help
        {
            get { return categoryHelp; }
        }

        /// <summary>
        /// Gets the performance counter category Type.
        /// </summary>
        /// <value>
        /// Performance counter category type.
        /// </value>
        public PerformanceCounterCategoryType CategoryType
        {
            get { return categoryType; }
        }

        /// <summary>
        /// Gets a writable instance of a performance counter in this category.
        /// </summary>
        /// <value>
        /// Writable instance of a performance counter in this category.
        /// </value>
        public PerformanceCounter this[string counterName]
        {
            get { return GetCounter(categoryName, counterName, false); }
        }

        /// <summary>
        /// Gets the counter creation data collection
        /// </summary>
        /// <remarks>
        /// Can be passed to a PerformanceCounterInstaller.
        /// </remarks>
        public CounterCreationDataCollection Counters
        {
            get { return counters; }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Gets an instance of the specified performance counter in this category.
        /// </summary>
        /// <param name="counterName">Performance counter name.</param>
        /// <param name="instanceName">Performance counter instance name.</param>
        /// <param name="readOnly">If true, the returned counter is readonly. If false, the returned counter is writable.</param>
        /// <returns>Performance counter instance.</returns>
        public PerformanceCounter GetCounter(string counterName, string instanceName, bool readOnly)
        {
            return GetCounter(categoryName, counterName, instanceName, readOnly);
        }

        /// <summary>
        /// Gets a readonly instance of the specified performance counter in this category.
        /// </summary>
        /// <param name="counterName">Performance counter name.</param>
        /// <param name="instanceName">Performance counter instance name.</param>
        /// <returns>Performance counter instance.</returns>
        public PerformanceCounter GetCounter(string counterName, string instanceName)
        {
            return GetCounter(counterName, instanceName, false);
        }

        /// <summary>
        /// Gets an instance of the specified performance counter in this category.
        /// </summary>
        /// <param name="counterName">Performance counter name.</param>
        /// <param name="readOnly">If true, the returned counter is readonly. If false, the returned counter is writable.</param>
        /// <returns>Performance counter instance.</returns>
        public PerformanceCounter GetCounter(string counterName, bool readOnly)
        {
            return GetCounter(categoryName, counterName, string.Empty, readOnly);
        }

        /// <summary>
        /// Gets a readonly instance of the specified performance counter in this category.
        /// </summary>
        /// <param name="counterName">Performance counter name</param>
        /// <returns>Performance counter instance.</returns>
        public PerformanceCounter GetCounter(string counterName)
        {
            return GetCounter(counterName, false);
        }

        /// <summary>
        /// Adds a performance counter of the given type to the category collection.
        /// </summary>
        /// <remarks>
        /// Adds a performance counter of the given type to the category collection.
        /// </remarks>
        /// <param name="name">Performance counter name.</param>
        /// <param name="type">Performance counter type.</param>
        /// <param name="help">Performance counter help text.</param>
        public void AddCounter(string name, PerformanceCounterType type, string help)
        {
            CounterCreationData counter = new CounterCreationData();
            counter.CounterName = name;
            counter.CounterType = type;
            if (help != null)
                counter.CounterHelp = help;

            counters.Add(counter);
        }

        /// <summary>
        /// Adds a performance counter of the given type to the category collection.
        /// </summary>
        /// <remarks>
        /// Adds a performance counter of the given type to the category collection.
        /// </remarks>
        /// <param name="name">Performance counter name.</param>
        /// <param name="type">Performance counter type.</param>
        public void AddCounter(string name, PerformanceCounterType type)
        {
            AddCounter(name, type, null);
        }

        /// <summary>
        /// Adds a NumberOfItems64 performance counter to the category collection.
        /// </summary>
        /// <remarks>
        /// Adds a NumberOfItems64 performance counter to the category collection.
        /// </remarks>
        /// <param name="name">Performance counter name.</param>
        /// <param name="help">Performance counter help text.</param>
        public void AddNumberCounter(string name, string help)
        {
            AddCounter(name, PerformanceCounterType.NumberOfItems64, help);
        }

        /// <summary>
        /// Adds a NumberOfItems64 performance counter to the category collection.
        /// </summary>
        /// <remarks>
        /// Adds a NumberOfItems64 performance counter to the category collection.
        /// </remarks>
        /// <param name="name">Performance counter name.</param>
        public void AddNumberCounter(string name)
        {
            AddCounter(name, PerformanceCounterType.NumberOfItems64, null);
        }

        /// <summary>
        /// Adds a RateOfCountsPerSecond64 performance counter to the category collection.
        /// </summary>
        /// <remarks>
        /// Adds a RateOfCountsPerSecond64 performance counter to the category collection.
        /// </remarks>
        /// <param name="name">Performance counter name.</param>
        /// <param name="help">Performance counter help text.</param>
        public void AddRateCounter(string name, string help)
        {
            AddCounter(name, PerformanceCounterType.RateOfCountsPerSecond64, help);
        }

        /// <summary>
        /// Adds a RateOfCountsPerSecond64 performance counter to the category collection.
        /// </summary>
        /// <remarks>
        /// Adds a RateOfCountsPerSecond64 performance counter to the category collection.
        /// </remarks>
        /// <param name="name">Performance counter name.</param>
        public void AddRateCounter(string name)
        {
            AddCounter(name, PerformanceCounterType.RateOfCountsPerSecond64);
        }

        /// <summary>
        /// Adds a AverageCount64 performance counter to the category collection.
        /// </summary>
        /// <remarks>
        /// Also adds the required base counter.
        /// </remarks>
        /// <param name="name">Performance counter name.</param>
        /// <param name="help">Performance counter help text.</param>
        public void AddAverageCounter(string name, string help)
        {
            // add average counter
            AddCounter(name, PerformanceCounterType.AverageCount64, help);
            // add the corresponding base counter
            AddCounter(name + "Base", PerformanceCounterType.AverageBase, null);
        }

        /// <summary>
        /// Adds a AverageCount64 performance counter to the category collection.
        /// </summary>
        /// <remarks>
        /// Also adds the required base counter.
        /// </remarks>
        /// <param name="name">Performance counter name.</param>
        public void AddAverageCounter(string name)
        {
            AddAverageCounter(name, null);
        }

        /// <summary>
        /// Adds a RawFraction performance counter to the category collection.
        /// </summary>
        /// <remarks>
        /// Also adds the required base counter.
        /// </remarks>
        /// <param name="name">Performance counter name.</param>
        /// <param name="help">Performance counter help text.</param>
        public void AddFractionCounter(string name, string help)
        {
            // add average counter
            AddCounter(name, PerformanceCounterType.RawFraction, help);
            // add the corresponding base counter
            AddCounter(name + "Base", PerformanceCounterType.RawBase, null);
        }

        /// <summary>
        /// Adds a RawFraction performance counter to the category collection.
        /// </summary>
        /// <remarks>
        /// Also adds the required base counter.
        /// </remarks>
        /// <param name="name">Performance counter name.</param>
        public void AddFractionCounter(string name)
        {
            AddFractionCounter(name, null);
        }


        /// <summary>
        /// Adds all performance counter for the specified Type to this category.
        /// </summary>
        /// <remarks>
        /// Performance category name of the Type must match the one of this category instance.
        /// </remarks>
        /// <param name="type">Type</param>
        public void AddCounters(Type type)
        {
            PerformanceCounterCategoryAttribute category = GetCategory(type);
            if (category == null)
                throw new ArgumentException(String.Format("Type {0} has no PerformanceCounterCategory attribute", type.Name), "type");

            if (category.Name != this.categoryName)
                throw new ArgumentException("Category names do not match");

            _AddCounters(type);
        }

        /// <summary>
        /// Indicates if the performance counter category exists.
        /// </summary>
        /// <remarks>
        /// Indicates if the performance counter category exists.
        /// </remarks>
        /// <returns>True if it does exist, false otherwise.</returns>
        public bool Exists()
        {
            return Exists(categoryName);
        }

        /// <summary>
        /// Creates performance counter category and counters.
        /// </summary>
        /// <remarks>
        /// If the category already exists only non existing counters are added.
        /// </remarks>
        public void Create()
        {
            if (!Exists(categoryName))
            {
                // category does not exist, create
                PerformanceCounterCategory.Create(
                    categoryName,
                    categoryHelp != null ? categoryHelp : "",
                    categoryType,
                    counters);
            }
        }

        /// <summary>
        /// Deletes the performance counter category and counters.
        /// </summary>
        /// <remarks>
        /// Deletes the performance counter category and counters.
        /// </remarks>
        public void Delete()
        {
            Delete(categoryName);
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Gets the performance counter category attribute attached to the type.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="type"></param>
        /// <returns>The performance counter category attribute on success, null otherwise</returns>
        private PerformanceCounterCategoryAttribute GetCategory(Type type)
        {
            // get category attribute
            object[] attributes = type.GetCustomAttributes(typeof(PerformanceCounterCategoryAttribute), false);

            // we don't have performance counter category, give up
            if (attributes.Length < 1) return null;

            return (PerformanceCounterCategoryAttribute)attributes[0];
        }

        /// <summary>
        /// Populates the CounterCreationDataCollection for a given type.
        /// </summary>
        /// <param name="type">Type to search for performance counters.</param>
        private void _AddCounters(Type type)
        {
            foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic))
            {
                // ignore member if it is not a performance counter
                if (field.FieldType != typeof(PerformanceCounter)) continue;

                // get the performance counter attribute
                object[] attributes = field.GetCustomAttributes(typeof(PerformanceCounterAttribute), false);
                // ignore it if it has no performance counter attribute set
                if (attributes.Length < 1) continue;

                // assign the performance counter
                PerformanceCounterAttribute counter = (PerformanceCounterAttribute)attributes[0];
                // only create a counter with multiple instances once 
                if (counter.Instance != string.Empty && Exists(counter))
                    continue;

                AddCounter(counter.Name, counter.Type, counter.Help);

                // create base counter if needed
                switch (counter.Type)
                {
                    case PerformanceCounterType.AverageCount64:
                    case PerformanceCounterType.AverageTimer32:
                        AddCounter(counter.Name + "Base", PerformanceCounterType.AverageBase);
                        break;
                    case PerformanceCounterType.RawFraction:
                        AddCounter(counter.Name + "Base", PerformanceCounterType.RawBase);
                        break;
                    case PerformanceCounterType.CounterMultiTimer:
                    case PerformanceCounterType.CounterMultiTimerInverse:
                    case PerformanceCounterType.CounterMultiTimer100Ns:
                    case PerformanceCounterType.CounterMultiTimer100NsInverse:
                        AddCounter(counter.Name + "Base", PerformanceCounterType.CounterMultiBase);
                        break;
                    case PerformanceCounterType.SampleCounter:
                    case PerformanceCounterType.SampleFraction:
                        AddCounter(counter.Name + "Base", PerformanceCounterType.SampleBase);
                        break;
                    default: break;
                }
            }
        }

        /// <summary>
        /// Checks if a counter by the same name already exists in the counter creation data collection.
        /// </summary>
        /// <remarks>
        /// Counter names must be unique within a category.
        /// </remarks>
        /// <param name="counter">Performance counter attribute.</param>
        /// <returns><b>True</b> if the counter already exists, <b>false</b> otherwise.</returns>
        private bool Exists(PerformanceCounterAttribute counter)
        {
            foreach (CounterCreationData creationData in counters)
            {
                if (creationData.CounterName == counter.Name)
                    return true;
            }

            return false;
        }

        #endregion

        #region Static Methods

        /// <summary>
        /// Gets a performance counter instance for a given name and category.
        /// </summary>
        /// <remarks>
        /// Gets a performance counter instance for a given name and category.
        /// </remarks>
        /// <param name="categoryName">Performance counter category.</param>
        /// <param name="counterName">Performance counter name.</param>
        /// <param name="instanceName">Performance counter instance name.</param>
        /// <param name="readOnly">ReadOnly</param>
        /// <returns>Performance counter instance.</returns>
        public static PerformanceCounter GetCounter(string categoryName, string counterName, string instanceName, bool readOnly)
        {
            return new PerformanceCounter(categoryName, counterName, instanceName, readOnly);
        }

        /// <summary>
        /// Checks if a performance counter category exists.
        /// </summary>
        /// <param name="categoryName">Performance counter category name.</param>
        /// <returns>True if the category exists, false otherwise.</returns>
        public static bool Exists(string categoryName)
        {
            return PerformanceCounterCategory.Exists(categoryName);
        }

        /// <summary>
        /// Deletes the specified performance counter category and counters.
        /// </summary>
        /// <remarks>
        /// Deletes the specified performance counter category and counters.
        /// </remarks>
        /// <param name="categoryName">Performance counter category name.</param>
        public static void Delete(string categoryName)
        {
            PerformanceCounterCategory.Delete(categoryName);
        }

        /// <summary>
        /// Creates instances for all performance counter members in the given type.
        /// </summary>
        /// <remarks>
        /// The type must have the PerformanceCounterCategory attribute set. Each performance counter
        /// member must be static and tagged with a PerformanceCounter attribute.
        /// </remarks>
        /// <param name="type">Type to instantiate counters</param>
        /// <returns><b>True</b> if counters were created successfully, <b>false</b> otherwise.</returns>
        public static bool CreateCounters(Type type)
        {
            return CreateCounters(type, null);
        }

        /// <summary>
        /// Creates instances for all performance counter members in the given type.
        /// </summary>
        /// <remarks>
        /// The type must have the PerformanceCounterCategory attribute set. Each performance counter
        /// member must be static and tagged with a PerformanceCounter attribute.
        /// </remarks>
        /// <param name="type">Type to instantiate counters</param>
        /// <param name="instance">Instance to assign performance counters to.</param>
        /// <returns><b>True</b> if counters were created successfully, <b>false</b> otherwise.</returns>
        public static bool CreateCounters(Type type, object instance)
        {
            Debug.Assert(instance == null || type == instance.GetType() || instance.GetType().IsSubclassOf(type));

            // get category attribute
            object[] attributes = type.GetCustomAttributes(typeof(PerformanceCounterCategoryAttribute), false);

            // we don't have performance counter category, we are done
            if (attributes.Length < 1) return false;
            string categoryName = ((PerformanceCounterCategoryAttribute)attributes[0]).Name;

            bool result = false;
            try
            {
                if (PerformanceCounterCategory.Exists(categoryName))
                {
                    // get the category type
                    PerformanceCounterCategory category = new PerformanceCounterCategory(categoryName);
                    PerformanceCounterCategoryType categoryType = category.CategoryType;

                    foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic))
                    {
                        // ignore member if it is not a performance counter or it is not static
                        if (field.FieldType != typeof(PerformanceCounter) || (instance == null && !field.IsStatic)) continue;

                        // get the performance counter attribute
                        attributes = field.GetCustomAttributes(typeof(PerformanceCounterAttribute), false);
                        // ignore it if it has no performance counter attribute set
                        if (attributes.Length < 1) continue;

                        // get the counter attribute data
                        PerformanceCounterAttribute counter = (PerformanceCounterAttribute)attributes[0];
                        // use a default instance name if the the counter does not have one and the category is marked MultiInstance
                        string instanceName = (counter.Instance == String.Empty && category.CategoryType == PerformanceCounterCategoryType.MultiInstance) ? "_default" : counter.Instance;
                        // assign the performance counter
                        field.SetValue(instance, new PerformanceCounter(categoryName, counter.Name, instanceName, false));

                        // create base counter if needed
                        switch (counter.Type)
                        {
                            case PerformanceCounterType.AverageCount64:
                            case PerformanceCounterType.RawFraction:
                            case PerformanceCounterType.SampleFraction:
                                FieldInfo baseCounter = type.GetField(field.Name + "Base", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
                                if (baseCounter != null)
                                    baseCounter.SetValue(instance, new PerformanceCounter(categoryName, counter.Name + "Base", instanceName, false));
                                break;
                            default: break;
                        }
                    }
                    result = true;
                }
            }
            catch (Exception)
            {
                result = false;
            }

            return result;
        }

        #endregion
    }
}
